/*
 * CampaniaXml.cpp
 *
 * Author: Grupo Nro.
 */

#include "CampaniaXml.h"

CampaniaXml::CampaniaXml() {
	string claveCampaniaXml = "campaniaXml";

	Properties properties;
	this->nombreDocumento = properties.getProperty(claveCampaniaXml.c_str());

	 this->documento.LoadFile(this->nombreDocumento.c_str());

	 if (this->documento.ErrorID() != 0){
		string mensajeError = "Error al intentar abrir el documento xml especificado en el archivo de properties.";
		throw ParserException(mensajeError);
	}
	cargarDatos();
}

CampaniaXml::CampaniaXml(string nombreArchivo) {
	this->nombreDocumento = nombreArchivo;
	this->documento.LoadFile(this->nombreDocumento.c_str());

	if (this->documento.ErrorID() != 0){
		string mensajeError = "Error al intentar abrir el documento xml:";
		mensajeError.append(nombreArchivo.c_str());
		throw ParserException(mensajeError);
	}
	cargarDatos();
}

void CampaniaXml::creacionEstructuraInicial(){
	tinyxml2::XMLElement* elementoCampanias = this->documento.NewElement(CAMPANIAS);
	this->documento.InsertEndChild(elementoCampanias);

	this->documento.SaveFile(this->nombreDocumento.c_str(), false);
	this->documento.LoadFile(this->nombreDocumento.c_str());
	if (this->documento.ErrorID() != 0){
		string mensajeError = "Error al intentar guardar y reabrir el documento xml.";
		throw ParserException(mensajeError);
	}
}

void CampaniaXml::cargarDatos(){
	// Verifica que el root sea "campanias"
	tinyxml2::XMLElement* root = this->documento.RootElement();
	if (root == NULL) {
		creacionEstructuraInicial();
		root = this->documento.RootElement();
	}

	if (strcmp(root->Value( ), CAMPANIAS) != 0) {
		string mensajeError = "Error en la estructura del archivo. Tiene como root:";
		mensajeError.append(root->Value());
		mensajeError.append(". Se esperaba que tuviera:");
		mensajeError.append(string(CAMPANIAS).c_str());
		throw ParserException(mensajeError);
	}

	// Lista de campanias
	for (tinyxml2::XMLElement* campania = root->FirstChildElement();
			campania; campania = campania->NextSiblingElement()) {
		campanias.push_back(convertirACampania(campania));
	}
}

Campania * CampaniaXml::convertirACampania(tinyxml2::XMLElement* elementoCampania){
	// Verifica que el elementoCampania corresponda a un elemento "campania"
	if (strcmp(elementoCampania->Value( ), CAMPANIA) != 0) {
		string mensajeError = "Error en la estructura del archivo. Tiene como elemento de campania:";
		mensajeError.append(elementoCampania->Value());
		mensajeError.append(". Se esperaba que tuviera:");
		mensajeError.append(string(CAMPANIA).c_str());
		throw ParserException(mensajeError);
	}

	int cantJugadoresMin = 0;
	string imagen;
	int nivelDificultad = 0;

	int idCampaniaSeteado = Utils::stringToInt(string(elementoCampania->Attribute(CAMPANIA_ID)));

	//Nombre campania
	string nombre = string(elementoCampania->Attribute(CAMPANIA_NOMBRE));
	if (nombre.empty()){
		string mensajeError = "Error:: La campania número " + Utils::intToString(idCampaniaSeteado) + " no posee nombre.";
		throw ParserException(mensajeError);
	}

	tinyxml2::XMLElement* element = elementoCampania->FirstChildElement();
	//Cantidad minima de jugadores
	if (element && strcmp(element->Value(), CAMPANIA_CANT_MINIMA_JUGADORES) == 0) {
		cantJugadoresMin = Utils::stringToInt(element->GetText());
	} else {
		string mensajeError = "Error al obtener la cantidad minima de jugadores para la campania número "
				+ Utils::intToString(idCampaniaSeteado) + ".";
		throw ParserException(mensajeError);
	}
	// Path imagen
	element = element->NextSiblingElement();
	if (element && strcmp(element->Value(), CAMPANIA_PATH_IMAGEN) == 0) {
		imagen = element->GetText();
	} else {
		string mensajeError = "Error al obtener el path de la imagen para la campania número "
				+ Utils::intToString(idCampaniaSeteado) + ".";
		throw ParserException(mensajeError);
	}
	// Nivel de dificultad
	element = element->NextSiblingElement();
	if (element && strcmp(element->Value(), CAMPANIA_NIVEL_DIFICULTAD) == 0) {
		nivelDificultad = Utils::stringToInt(element->GetText());
	} else {
		string mensajeError = "Error al obtener el nivel de dificultad para la campania número "
				+ Utils::intToString(idCampaniaSeteado) + ".";
		throw ParserException(mensajeError);
	}

	Campania * campania = new Campania(idCampaniaSeteado, cantJugadoresMin, imagen, nivelDificultad, nombre);

	// Niveles
	element = element->NextSiblingElement();
	if (element && strcmp(element->Value(), CAMPANIA_NIVELES) == 0) {
		int cantidadNiveles = 0;
		for (tinyxml2::XMLElement* nivel = element->FirstChildElement();
				nivel; nivel = nivel->NextSiblingElement()) {
			cantidadNiveles++;
			if (nivel && strcmp(nivel->Value(), NIVEL) == 0) {
				int nivelNroOrden = Utils::stringToInt(nivel->Attribute(NIVEL_NRO_ORDEN));
				Nivel * nivelObject = convertirANivel(nivel);
				campania->addNivel(nivelNroOrden, *nivelObject);
			} else {
				string mensajeError = "Error al obtener un nivel para la campania número "
						+ Utils::intToString(idCampaniaSeteado) + ".";
				throw ParserException(mensajeError);
			}
		}
	} else {
		string mensajeError = "Error:: No existen niveles para la campania número "
				+ Utils::intToString(idCampaniaSeteado) + ".";
		throw ParserException(mensajeError);
	}

	return campania;
}

Nivel * CampaniaXml::convertirANivel(tinyxml2::XMLElement* elementoNivel){
	int idNivelSeteado = Utils::stringToInt(string(elementoNivel->Attribute(NIVEL_ID)));

	Nivel * nivel = new Nivel(idNivelSeteado);
	tinyxml2::XMLElement* element = elementoNivel->FirstChildElement();
	//Mapa
	if (element && strcmp(element->Value(), MAPA) == 0) {
		//map_height
		nivel->setMapHeight(Utils::stringToInt(element->Attribute(MAPA_HEIGHT)));
		//map_width
		nivel->setMapWidth(Utils::stringToInt(element->Attribute(MAPA_WIDTH)));
		//number_of_enemies
		nivel->setNumberOfEnemies(Utils::stringToInt(element->Attribute(MAPA_NUMBER_OF_ENEMIES)));

		//map_objects
		element = element->FirstChildElement();
		if (element && strcmp(element->Value(), MAPA_MAP_OBJECTS) == 0) {
			for (tinyxml2::XMLElement* mapObject = element->FirstChildElement();
					mapObject; mapObject = mapObject->NextSiblingElement()) {
				if (mapObject && strcmp(mapObject->Value(), MAPA_MAP_OBJECT) == 0) {
					string tipo = mapObject->Attribute(MAPA_MAP_OBJECT_TIPO);
					int id = Utils::stringToInt(mapObject->Attribute(MAPA_MAP_OBJECT_ID));
					int posicionX = Utils::stringToInt(mapObject->Attribute(MAPA_MAP_OBJECT_POSICION_X));
					int posicionY = Utils::stringToInt(mapObject->Attribute(MAPA_MAP_OBJECT_POSICION_Y));
					nivel->addMapObject(MapObjectFactory::build(tipo, id, posicionX, posicionY));
				} else {
					string mensajeError = "Error al obtener un map object para el nivel número "
							+ Utils::intToString(idNivelSeteado) + ".";
					throw ParserException(mensajeError);
				}
			}
		}

		//plantas
		element = element->NextSiblingElement();
		if (element && strcmp(element->Value(), MAPA_PLANTS) == 0) {
			for (tinyxml2::XMLElement* plant = element->FirstChildElement();
					plant; plant = plant->NextSiblingElement()) {
				if (plant && strcmp(plant->Value(), MAPA_PLANT) == 0) {
					int id = Utils::stringToInt(plant->Attribute(MAPA_PLANT_ID));
					int posicionX = Utils::stringToInt(plant->Attribute(MAPA_PLANT_POSICION_X));
					int posicionY = Utils::stringToInt(plant->Attribute(MAPA_PLANT_POSICION_Y));
					int shoot_frequency = Utils::stringToInt(plant->Attribute(MAPA_PLANT_SHOOT_FREQUENCY));
					int facing = Utils::stringToInt(plant->Attribute(MAPA_PLANT_FACING));

					nivel->addPlant(*(new Plant(id, posicionX, posicionY, shoot_frequency, facing)));
				} else {
					string mensajeError = "Error al obtener una planta para el nivel número "
							+ Utils::intToString(idNivelSeteado) + ".";
					throw ParserException(mensajeError);
				}
			}
		}

		//spawners
		element = element->NextSiblingElement();
		if (element && strcmp(element->Value(), MAPA_SPAWNERS) == 0) {
			for (tinyxml2::XMLElement* spawner = element->FirstChildElement();
					spawner; spawner = spawner->NextSiblingElement()) {
				if (spawner && strcmp(spawner->Value(), MAPA_SPAWNER) == 0) {
					string tipo = spawner->Attribute(MAPA_SPAWNER_TIPO);
					int id = Utils::stringToInt(spawner->Attribute(MAPA_SPAWNER_ID));
					int posicionX = Utils::stringToInt(spawner->Attribute(MAPA_SPAWNER_POSICION_X));
					int posicionY = Utils::stringToInt(spawner->Attribute(MAPA_SPAWNER_POSICION_Y));

					if (tipo.compare(string(SPAWNER_BLUE_ZOMBIE).c_str()) == 0){
						EnemySpawner * enemySpawner = new EnemySpawner(ZOMBIE_BLUE, id, posicionX, posicionY);
						nivel->addSpawner(*enemySpawner);
					} else if (tipo.compare(string(SPAWNER_GREEN_ZOMBIE).c_str()) == 0){
						EnemySpawner * enemySpawner = new EnemySpawner(ZOMBIE_GREEN, id, posicionX, posicionY);
						nivel->addSpawner(*enemySpawner);
					} else if (tipo.compare(string(SPAWNER_RED_ZOMBIE).c_str()) == 0){
						EnemySpawner * enemySpawner = new EnemySpawner(ZOMBIE_RED, id, posicionX, posicionY);
						nivel->addSpawner(*enemySpawner);
					} else {
						string mensajeError = "Error en el tipo de spawner seteado para el nivel número "
								+ Utils::intToString(idNivelSeteado) + ".";
						throw ParserException(mensajeError);
					}
				} else {
					string mensajeError = "Error al obtener un spawners para el nivel número "
							+ Utils::intToString(idNivelSeteado) + ".";
					throw ParserException(mensajeError);
				}
			}
		}

		//bomberman_spawns
		element = element->NextSiblingElement();
		if (element && strcmp(element->Value(), MAPA_SPAWNER_BOMBERMAN_SPAWNERS) == 0) {
			for (tinyxml2::XMLElement* bomberman_spawns = element->FirstChildElement();
					bomberman_spawns; bomberman_spawns = bomberman_spawns->NextSiblingElement()) {
				if (bomberman_spawns && strcmp(bomberman_spawns->Value(), MAPA_SPAWNER_BOMBERMAN_SPAWNER) == 0) {
					int posicionX = Utils::stringToInt(bomberman_spawns->Attribute(MAPA_SPAWNER_BOMBERMAN_SPAWNER_POSICION_X));
					int posicionY = Utils::stringToInt(bomberman_spawns->Attribute(MAPA_SPAWNER_BOMBERMAN_SPAWNER_POSICION_Y));

					nivel->addBombermanSpawnPoint(posicionX, posicionY);
				} else {
					string mensajeError = "Error al obtener los datos para un bomberman spawner para el nivel número "
							+ Utils::intToString(idNivelSeteado) + ".";
					throw ParserException(mensajeError);
				}
			}
		}

		//Tile Map
		element = element->NextSiblingElement();
		if (element && strcmp(element->Value(), MAPA_TILE_MAP) == 0) {
			string tile_map = element->Attribute(MAPA_TILE_MAP_CONTENIDO);
			nivel->setTileMapRepresentation(tile_map);
		}

	} else {
		string mensajeError = "Error al obtener los datos del mapa para el nivel número "
				+ Utils::intToString(idNivelSeteado) + ".";
		throw ParserException(mensajeError);
	}

	return nivel;
}

CampaniaXml::~CampaniaXml() {
}

void CampaniaXml::grabar(){
	this->documento.SaveFile(this->nombreDocumento.c_str(), false);
}

vector<Campania*> & CampaniaXml::getCampanias(){
	return this->campanias;
}

void CampaniaXml::addCampania(Campania * campania){
	//Lo agrego al xml
	agregarCampaniaXml(campania);

	//Lo agrego a memoria
	campanias.push_back(campania);
}

void CampaniaXml::agregarCampaniaXml(Campania * campania){
	//Lo agrego al xml
	tinyxml2::XMLElement * elementoCampania = this->documento.NewElement(CAMPANIA);
	//Id
	elementoCampania->SetAttribute(CAMPANIA_ID, campania->getId());
	//Nombre
	elementoCampania->SetAttribute(CAMPANIA_NOMBRE, campania->getNombre().c_str());
	//cantidadMinimaJugadores
	tinyxml2::XMLElement * cantJugadoresElement = this->documento.NewElement(CAMPANIA_CANT_MINIMA_JUGADORES);
	cantJugadoresElement->SetText(Utils::intToString(campania->getCantJugadoresMin()).c_str());
	elementoCampania->InsertEndChild(cantJugadoresElement);
	//pathImagen
	tinyxml2::XMLElement * pathImagenElement = this->documento.NewElement(CAMPANIA_PATH_IMAGEN);
	pathImagenElement->SetText(campania->getImagen().c_str());
	elementoCampania->InsertEndChild(pathImagenElement);
	//nivelDificultad
	tinyxml2::XMLElement * nivelDificultadElement = this->documento.NewElement(CAMPANIA_NIVEL_DIFICULTAD);
	nivelDificultadElement->SetText(Utils::intToString(campania->getNivelDificultad()).c_str());
	elementoCampania->InsertEndChild(nivelDificultadElement);

	//Niveles
	agregarNivelesXml(elementoCampania, campania->getSecuenciaNiveles());

	tinyxml2::XMLElement* root = this->documento.FirstChildElement(CAMPANIAS);

	root->InsertEndChild(elementoCampania);

	this->documento.SaveFile(this->nombreDocumento.c_str(), false);
	this->documento.LoadFile(this->nombreDocumento.c_str());
	if (this->documento.ErrorID() != 0){
		string mensajeError = "Error al intentar guardar y reabrir el documento xml.";
		throw ParserException(mensajeError);
	}
}

void CampaniaXml::agregarNivelesXml(tinyxml2::XMLElement * elementoBase,
		map<int, Nivel*> secuenciasNiveles){
	//niveles
	tinyxml2::XMLElement * nivelesElement = this->documento.NewElement(CAMPANIA_NIVELES);

	map<int, Nivel*>::const_iterator
		mit(secuenciasNiveles.begin()), mend(secuenciasNiveles.end());

	for (; mit != mend; ++mit){
		agregarNivelXml(nivelesElement, mit->first, *(mit->second));
	}

	elementoBase->InsertEndChild(nivelesElement);
}

void CampaniaXml::agregarNivelXml(tinyxml2::XMLElement * elementoBase,
		int secuenciaNivel, Nivel & nivel){
	tinyxml2::XMLElement * nivelElement = this->documento.NewElement(NIVEL);
	nivelElement->SetAttribute(NIVEL_ID, nivel.getId());
	nivelElement->SetAttribute(NIVEL_NRO_ORDEN, secuenciaNivel);
	tinyxml2::XMLElement * mapaElement = this->documento.NewElement(MAPA);
	mapaElement->SetAttribute(MAPA_HEIGHT, nivel.getMapHeight());
	mapaElement->SetAttribute(MAPA_WIDTH, nivel.getMapWidth());
	mapaElement->SetAttribute(MAPA_NUMBER_OF_ENEMIES, nivel.getNumberOfEnemies());

	//map_objects
	agregarMapObjectsXml(mapaElement, nivel.getMapObjects());

	//plants
	agregarPlantsXml(mapaElement, nivel.getPlants());

	//spawners
	agregarSpawnersXml(mapaElement, nivel.getSpawners());

	//bomberman_spawns
	agregarBombermanSpawnersXml(mapaElement, nivel.getBombermanSpawnPoints());

	//Tile map
	agregarTileMapXml(mapaElement, nivel.getTileMapRepresentation());

	nivelElement->InsertEndChild(mapaElement);

	elementoBase->InsertEndChild(nivelElement);
}

void CampaniaXml::agregarMapObjectsXml(tinyxml2::XMLElement * elementoBase,
		vector<MapObject*> & map_objects){
	//map_objects
	tinyxml2::XMLElement * mapObjectsElement = this->documento.NewElement(MAPA_MAP_OBJECTS);
	std::size_t i;
	for (i = 0; i < map_objects.size(); i++){
		tinyxml2::XMLElement * mapObjectElement = this->documento.NewElement(MAPA_MAP_OBJECT);
		mapObjectElement->SetAttribute(MAPA_MAP_OBJECT_TIPO, map_objects[i]->getTypeXml().c_str());
		mapObjectElement->SetAttribute(MAPA_MAP_OBJECT_ID, map_objects[i]->getId());
		mapObjectElement->SetAttribute(MAPA_MAP_OBJECT_POSICION_X, map_objects[i]->getX());
		mapObjectElement->SetAttribute(MAPA_MAP_OBJECT_POSICION_Y, map_objects[i]->getY());

		mapObjectsElement->InsertEndChild(mapObjectElement);
	}
	elementoBase->InsertEndChild(mapObjectsElement);
}

void CampaniaXml::agregarPlantsXml(tinyxml2::XMLElement * elementoBase,
		vector<Plant*> & plants){
	tinyxml2::XMLElement * plantsElement = this->documento.NewElement(MAPA_PLANTS);
	std::size_t i;
	for (i = 0; i < plants.size(); i++){
		tinyxml2::XMLElement * plantElement = this->documento.NewElement(MAPA_PLANT);
		plantElement->SetAttribute(MAPA_PLANT_ID, plants[i]->getId());
		plantElement->SetAttribute(MAPA_PLANT_POSICION_X, plants[i]->getX());
		plantElement->SetAttribute(MAPA_PLANT_POSICION_Y, plants[i]->getY());
		plantElement->SetAttribute(MAPA_PLANT_SHOOT_FREQUENCY, plants[i]->getShootFrequency());
		plantElement->SetAttribute(MAPA_PLANT_FACING, plants[i]->getFacing());

		plantsElement->InsertEndChild(plantElement);
	}
	elementoBase->InsertEndChild(plantsElement);
}

void CampaniaXml::agregarSpawnersXml(tinyxml2::XMLElement * elementoBase,
		vector<Spawner*> & spawners){
	//spawners
	tinyxml2::XMLElement * spawnersElement = this->documento.NewElement(MAPA_SPAWNERS);
	std::size_t i;
	for (i = 0; i < spawners.size(); i++){
		tinyxml2::XMLElement * spawnerElement = this->documento.NewElement(MAPA_SPAWNER);
		EnemySpawner * enemySpawner = (EnemySpawner*) spawners[i];
		//Tipo
		if (enemySpawner->getModelObject() == ZOMBIE_BLUE){
			spawnerElement->SetAttribute(MAPA_SPAWNER_TIPO, SPAWNER_BLUE_ZOMBIE);
		} else if (enemySpawner->getModelObject() == ZOMBIE_GREEN){
			spawnerElement->SetAttribute(MAPA_SPAWNER_TIPO, SPAWNER_GREEN_ZOMBIE);
		} else if (enemySpawner->getModelObject() == ZOMBIE_RED){
			spawnerElement->SetAttribute(MAPA_SPAWNER_TIPO, SPAWNER_RED_ZOMBIE);
		} else {
			string mensajeError = "Error en el tipo de spawner para el nivel.";
			throw ParserException(mensajeError);
		}

		spawnerElement->SetAttribute(MAPA_SPAWNER_ID, enemySpawner->getId());
		spawnerElement->SetAttribute(MAPA_SPAWNER_POSICION_X, enemySpawner->getSpawningX());
		spawnerElement->SetAttribute(MAPA_SPAWNER_POSICION_Y, enemySpawner->getSpawningY());

		spawnersElement->InsertEndChild(spawnerElement);
	}
	elementoBase->InsertEndChild(spawnersElement);
}

void CampaniaXml::agregarTileMapXml(tinyxml2::XMLElement * elementoBase,
		string & tileMap){
	//Tile Map
	tinyxml2::XMLElement * tileMapElement = this->documento.NewElement(MAPA_TILE_MAP);
	tileMapElement->SetAttribute(MAPA_TILE_MAP_CONTENIDO, tileMap.c_str());

	elementoBase->InsertEndChild(tileMapElement);
}

void CampaniaXml::deleteCampania(int idCampania){
	//Elimino del xml
	tinyxml2::XMLElement* root = this->documento.RootElement();
	if (strcmp(root->Value( ), CAMPANIAS) != 0) {
		string mensajeError = "Error en la estructura del archivo. Tiene como root:";
		mensajeError.append(root->Value());
		mensajeError.append(". Se esperaba que tuviera:");
		mensajeError.append(string(CAMPANIAS).c_str());
		throw ParserException(mensajeError);
	}

	// Lista de campanias
	bool encontrada = false;
	for (tinyxml2::XMLElement* campania = root->FirstChildElement();
			campania && !encontrada; campania = campania->NextSiblingElement()) {
		int idCampaniaSeteado = Utils::stringToInt(string(campania->Attribute(CAMPANIA_ID)));
		if (idCampaniaSeteado == idCampania){
			//Elimino elemento del xml
			this->documento.DeleteChild(campania);
			encontrada = true;
			this->documento.SaveFile(this->nombreDocumento.c_str(), false);
			this->documento.LoadFile(this->nombreDocumento.c_str());
			if (this->documento.ErrorID() != 0){
				string mensajeError = "Error al intentar guardar y reabrir el documento xml.";
				throw ParserException(mensajeError);
			}
		}
	}

	//Elimino de memoria
	if (encontrada){
		encontrada = false;
		std::size_t i = 0;
		while (i < this->campanias.size() && !encontrada){
			if (this->campanias[i]->getId() == idCampania){
				encontrada = true;
				delete this->campanias[i];
				this->campanias.erase(this->campanias.begin() + i);
			}
			i++;
		}
	}
}

void CampaniaXml::addNivel(int idCampania, Nivel * nivel,
		int nroOrdenSecuenciaNivel){
	//Agrego al xml
	tinyxml2::XMLElement* root = this->documento.RootElement();
	if (strcmp(root->Value( ), CAMPANIAS) != 0) {
		string mensajeError = "Error en la estructura del archivo. Tiene como root:";
		mensajeError.append(root->Value());
		mensajeError.append(". Se esperaba que tuviera:");
		mensajeError.append(string(CAMPANIAS).c_str());
		throw ParserException(mensajeError);
	}

	// Lista de campanias
	bool encontrada = false;
	for (tinyxml2::XMLElement* campania = root->FirstChildElement();
			campania && !encontrada; campania = campania->NextSiblingElement()) {
		int idCampaniaSeteado = Utils::stringToInt(string(campania->Attribute(CAMPANIA_ID)));
		if (idCampaniaSeteado == idCampania){
			encontrada = true;

			tinyxml2::XMLElement* nivelesElement = campania->FirstChildElement(CAMPANIA_NIVELES);
			if (nivelesElement){
				agregarNivelXml(nivelesElement, nroOrdenSecuenciaNivel, *nivel);
			} else {
				map<int, Nivel*> secuenciasNiveles;
				secuenciasNiveles[nroOrdenSecuenciaNivel] = nivel;
				agregarNivelesXml(campania, secuenciasNiveles);
			}
			this->documento.SaveFile(this->nombreDocumento.c_str(), false);
			this->documento.LoadFile(this->nombreDocumento.c_str());
			if (this->documento.ErrorID() != 0){
				string mensajeError = "Error al intentar guardar y reabrir el documento xml.";
				throw ParserException(mensajeError);
			}
		}
	}

	//Lo agrego a memoria
	encontrada = false;
	std::size_t i = 0;
	while (i < this->campanias.size() && !encontrada){
		if (this->campanias[i]->getId() == idCampania){
			this->campanias[i]->addNivel(nroOrdenSecuenciaNivel, *nivel);
			encontrada = true;
		}
		i++;
	}
}

void CampaniaXml::deleteNivel(int idCampania, int idNivel){
	tinyxml2::XMLElement* root = this->documento.RootElement();
	if (strcmp(root->Value( ), CAMPANIAS) != 0) {
		string mensajeError = "Error en la estructura del archivo. Tiene como root:";
		mensajeError.append(root->Value());
		mensajeError.append(". Se esperaba que tuviera:");
		mensajeError.append(string(CAMPANIAS).c_str());
		throw ParserException(mensajeError);
	}

	// Lista de campanias
	bool encontrada = false;
	bool nivelEncontrado = false;
	for (tinyxml2::XMLElement* campania = root->FirstChildElement();
			campania && !encontrada; campania = campania->NextSiblingElement()) {
		int idCampaniaSeteado = Utils::stringToInt(string(campania->Attribute(CAMPANIA_ID)));
		if (idCampaniaSeteado == idCampania){
			encontrada = true;
			tinyxml2::XMLElement* elemento = campania->FirstChildElement(CAMPANIA_NIVELES);
			if (elemento) {
				//Busco nivel
				for (tinyxml2::XMLElement* nivel = elemento->FirstChildElement();
						nivel && !nivelEncontrado; nivel = nivel->NextSiblingElement()) {
					int idNivelSeteado = Utils::stringToInt(string(nivel->Attribute(NIVEL_ID)));
					if (idNivelSeteado == idNivel){
						nivelEncontrado = true;
						//Elimino elemento del xml
						campania->DeleteChild(nivel);
						this->documento.SaveFile(this->nombreDocumento.c_str(), false);
						this->documento.LoadFile(this->nombreDocumento.c_str());
						if (this->documento.ErrorID() != 0){
							string mensajeError = "Error al intentar guardar y reabrir el documento xml.";
							throw ParserException(mensajeError);
						}
					}
				}
			}
		}
	}

	//Elimino de memoria
	if (nivelEncontrado){
		nivelEncontrado = false;
		int nroSecuencia = 0;
		std::size_t i = 0;
		while (i < this->campanias.size() && !nivelEncontrado){
			if (this->campanias[i]->getId() == idCampania){
				map<int, Nivel*>::const_iterator
					mit(this->campanias[i]->getSecuenciaNiveles().begin()),
					mend(this->campanias[i]->getSecuenciaNiveles().end());
				for (; mit != mend && !nivelEncontrado; ++mit){
					if (mit->second->getId() == idNivel){
						nivelEncontrado = true;
						nroSecuencia = mit->first;
						delete mit->second;
					}
				}
			}
			i++;
		}

		if (nivelEncontrado){
			map<int, Nivel*>::iterator it = this->campanias[i-1]->getSecuenciaNiveles().find(nroSecuencia);
			this->campanias[i-1]->getSecuenciaNiveles().erase(it);
		}
	}
}

void CampaniaXml::agregarBombermanSpawnersXml(tinyxml2::XMLElement * elementoBase,
			 vector<pair<int, int> >& bombermanSpawnPoints){
	//BombermanSpawners
	tinyxml2::XMLElement * bombermanSpawnersElement = this->documento.NewElement(MAPA_SPAWNER_BOMBERMAN_SPAWNERS);
	std::size_t i;
	for (i = 0; i < bombermanSpawnPoints.size(); i++){
		pair<int, int> parPosicion = bombermanSpawnPoints[i];

		tinyxml2::XMLElement * bombermanSpawnerElement = this->documento.NewElement(MAPA_SPAWNER_BOMBERMAN_SPAWNER);
		bombermanSpawnerElement->SetAttribute(MAPA_SPAWNER_BOMBERMAN_SPAWNER_POSICION_X, parPosicion.first);
		bombermanSpawnerElement->SetAttribute(MAPA_SPAWNER_BOMBERMAN_SPAWNER_POSICION_Y, parPosicion.second);

		bombermanSpawnersElement->InsertEndChild(bombermanSpawnerElement);
	}
	elementoBase->InsertEndChild(bombermanSpawnersElement);
}
